"""
Misc utils.

This code is part of KNIFE: cropping complexity, culling confusion, 
and cutting the crap since 2012
   
           .----------------._________________
           |=()=========---  \-----------     `\ 
      jgs  \_________________/^^^^^^^^^^^^^^^^^^

(c) 2012, Tim Menzies, tim@menzies.us, LGPL v3.0
"""

import re,sys,math

def chunks(l, n):
  "Divide 'l' into sub-lists of length 'n'."
  return [l[i:i+n] for i in range(0, len(l), n)]

def percentiles(l,bars,show,sort=True,filter=lambda x:x) :
  "Return the breaks seen after 'l' is divided into 'bars' blocks."
  if sort: l.sort()
  n = int(len(l)/bars)
  tmp= [filter(item[-1]) for item in chunks(l,n)]
  return [x for (n,x) in enumerate(tmp) if n in show] 
    
def nump (s):
  "Return a float or None."
  try:
    return float(s)
  except ValueError:
   return None

def hasArgs():
  "Returns true if the first arg has the form -com."
  return  len(sys.argv) > 1 and  '-' in sys.argv[1]

def runArgs() :
  """
   Utility for calling functions from command line.
   E.g. python file.py -function arg1 ag2 arg3 ...
   will generate the string  function(arg1,arg2,arg3,...).
  """
  def protect(string, fail=None):
    if string == 'True': return True
    if string == 'False':return False
    try:
      tmp = float(string)
      if tmp % 1 == 0:
        tmp = int(tmp)
        return tmp
    except Exception:
      return "'" + string + "'" 
  what = re.sub(r'^-',"",sys.argv[1])
  args=""
  if len(sys.argv) > 2:
    args = map(protect,sys.argv[2:])
    args = ", ".join(map(str,args))
  call = what + '(' + args + ')'
  return call

def s(*lst) : 
  "Return 'lst' as a string."
  return ', '.join(map(str,lst))

def stdev(n,s,s2): 
  """
  Returns standard deviation from 'n', the sum of
  a sample 's', and the of the squares of a sample 's2'.
  """
  return ((s2-((s*s)/n))/(n-1))**0.5

def val(x) :
  "Returns a value from 'x' (funcalls it if its a function)."
  def functionp(x) : return type(x).__name__ == 'function' 
  return x() if functionp(x) else x

def egs(*lst):
  "Runs a list of functions."
  for i in lst: 
    print '\n----|',i.func_name,'|','-'*40,'\n'
    i()

def medianSorted(lst):
  "Returns the median value of a list."
  z = len(lst)
  y = z/2
  if not z%2:
    return (lst[y-1] + lst[y]) / 2
  else:
    return lst[y]

def rows(file, n=0, bad=r'["\' \t\r\n]',sep=',') :
  """
  Generator for reading csv files. Returns each line,
  and its line number (split on 'sep', with all the 
  'bad' stuff deleted).
  """
  for line in open(file,'r') :
    n += 1
    yield n,re.sub(bad,"",line).split(sep)

    
